package com.ds.infrastructure.hyperspace.console.model.request.containerconfig.configdata;

import com.ds.infrastructure.hyperspace.console.dto.configdata.ConfigDataDTO;
import com.ds.infrastructure.hyperspace.console.dto.configdata.EndpointsDTO;
import com.ds.infrastructure.hyperspace.console.dto.configdata.NodesDTO;
import com.ds.infrastructure.hyperspace.console.dto.configdata.PipelinesDTO;
import com.ds.infrastructure.hyperspace.console.utils.ValidationUtil;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static com.ds.infrastructure.hyperspace.console.dto.configdata.ConfigDataDTO.ENDPOINT_TYPE.ENTRY;
import static com.ds.infrastructure.hyperspace.console.dto.configdata.ConfigDataDTO.ENDPOINT_TYPE.TARGET;

/**
 * @author: yaozhendong
 * @create: 2019-10-16 16:43
 **/
@Data
@NoArgsConstructor
public class ConfigDataForm {
    //
    @NotNull
    private Integer proxyId;
    //
    @NotBlank
    private String proxyName;
    private List<EntryEndpointForm> entryEndpoints;
    private List<TargetEndpointForm> targetEndpoints;
    private List<PipelinesForm> pipelines;

    public static ConfigDataDTO toDTO(ConfigDataForm form) {
        String targetEndpointNamespace = ConfigDataDTO.getNamespace(form.getProxyName(), TARGET.value);
        String entryEndpointNamespace = ConfigDataDTO.getNamespace(form.getProxyName(), ENTRY.value);
        //
        ConfigDataDTO configDataDTO = new ConfigDataDTO();
        configDataDTO.setProxyId(form.getProxyId());
        configDataDTO.setProxyName(form.getProxyName());
        //
        addEndpoint(form, configDataDTO);
        //
        addEntryEndpointDTO(form, configDataDTO, entryEndpointNamespace);
        //
        addTargetEndpointDTO(form, configDataDTO, targetEndpointNamespace);
        //
        addPipelineDTO(form, configDataDTO, targetEndpointNamespace, entryEndpointNamespace);

        return configDataDTO;
    }

    private static void addEndpoint(ConfigDataForm form, ConfigDataDTO configDataDTO) {
        if (form.getEntryEndpoints() == null
                && form.getTargetEndpoints() == null
                && form.getEntryEndpoints().isEmpty()
                && form.getTargetEndpoints().isEmpty()) {
            return;
        }
        configDataDTO.setEndpoints(new ArrayList<>());
    }

    private static void addPipelineDTO(ConfigDataForm form, ConfigDataDTO configDataDTO, String targetEndpointNamespace, String entryEndpointNamespace) {
        if (form.getPipelines() == null || form.getPipelines().isEmpty()) {
            return;
        }
        ValidationUtil.validateEntityList(form.getPipelines(), "pipelines");
        List<PipelinesDTO> pipelinesDTOList = new ArrayList<>();
        form.getPipelines().forEach(item -> pipelinesDTOList.add(PipelinesForm.toDTO(item, entryEndpointNamespace, targetEndpointNamespace)));
        configDataDTO.setPipelines(pipelinesDTOList);

    }

    private static void addEntryEndpointDTO(ConfigDataForm form, ConfigDataDTO configDataDTO, String entryEndpointNamespace) {
        if (form.getEntryEndpoints() == null || form.getEntryEndpoints().isEmpty()) {
            return;
        }
        ValidationUtil.validateEntityList(form.getEntryEndpoints(), "entryEndpoint");
        EndpointsDTO endpointsDTO = new EndpointsDTO();
        endpointsDTO.setNamespace(entryEndpointNamespace);
        endpointsDTO.setType(ENTRY.value);
        List<NodesDTO> nodesDTOList = new ArrayList<>();
        form.getEntryEndpoints().forEach(item -> nodesDTOList.add(EntryEndpointForm.toDTO(item)));
        endpointsDTO.setNodes(nodesDTOList);
        configDataDTO.getEndpoints().add(endpointsDTO);
    }

    private static void addTargetEndpointDTO(ConfigDataForm form, ConfigDataDTO configDataDTO, String targetEndpointNamespace) {
        if (form.getTargetEndpoints() == null || form.getTargetEndpoints().isEmpty()) {
            return;
        }
        ValidationUtil.validateEntityList(form.getTargetEndpoints(), "targetEndpoint");
        EndpointsDTO endpointsDTO = new EndpointsDTO();
        endpointsDTO.setNamespace(targetEndpointNamespace);
        endpointsDTO.setType(TARGET.value);
        List<NodesDTO> nodesDTOList = new ArrayList<>();
        form.getTargetEndpoints().forEach(item -> nodesDTOList.add(TargetEndpointForm.toDTO(item)));
        endpointsDTO.setNodes(nodesDTOList);
        configDataDTO.getEndpoints().add(endpointsDTO);
    }

    public static ConfigDataForm toVO(ConfigDataDTO dto) {
        ConfigDataForm form = new ConfigDataForm();
        form.setProxyId(dto.getProxyId());
        form.setProxyName(dto.getProxyName());
        //
        addEntryEndpointForm(dto, form);
        //
        addTargetEndpointForm(dto, form);
        //
        addPipelinesForm(dto, form);
        return form;
    }

    private static void addPipelinesForm(ConfigDataDTO dto, ConfigDataForm form) {
        if (dto.getPipelines() == null || dto.getPipelines().isEmpty()) {
            return;
        }
        List<PipelinesForm> pipelinesFromList = new ArrayList<>();
        dto.getPipelines().forEach(item -> pipelinesFromList.add(PipelinesForm.toVO(item)));
        form.setPipelines(pipelinesFromList);
    }

    private static void addEntryEndpointForm(ConfigDataDTO dto, ConfigDataForm form) {
        if (dto.getEndpoints() == null || dto.getEndpoints().isEmpty()) {
            return;
        }
        List<EntryEndpointForm> entryEndpointFormsList = new ArrayList<>();
        Optional<EndpointsDTO> first = dto.getEndpoints().stream()
                .filter(item -> ENTRY.value.equals(item.getType())).findFirst();
        if (!first.isPresent()) {
            return;
        }
        first.get().getNodes().forEach(item -> entryEndpointFormsList.add(EntryEndpointForm.toVO(item)));
        form.setEntryEndpoints(entryEndpointFormsList);
    }

    private static void addTargetEndpointForm(ConfigDataDTO dto, ConfigDataForm form) {
        if (dto.getEndpoints() == null || dto.getEndpoints().isEmpty()) {
            return;
        }
        List<TargetEndpointForm> targetEndpointFormList = new ArrayList<>();
        Optional<EndpointsDTO> first = dto.getEndpoints().stream()
                .filter(item -> TARGET.value.equals(item.getType())).findFirst();
        if (!first.isPresent()) {
            return;
        }
        first.get().getNodes().forEach(item -> targetEndpointFormList.add(TargetEndpointForm.toVO(item)));
        form.setTargetEndpoints(targetEndpointFormList);
    }
}
